<template>
  <el-dialog ref="saverRef" v-model="dialogVisible" :title="dialogType + saverConfig.title" :width="saverConfig.width" destroy-on-close>
    <el-form ref="ruleFormRef" :model="formData" :rules="rules" :label-width="formConfig.labelWidth" :size="formConfig.size">
      <el-form-item :label="item.label + ':'" :prop="item.prop" v-for="item in formItems" :key="item.prop">
        <component
          :is="ItemMap[item.name]"
          :item-config="item"
          :item-value="formData[item.prop]"
          :corr-value="item.corrProp ? formData[item.corrProp] : null"
          :ref="item.prop"
          @update="handleUpdate"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="resetForm(ruleFormRef)">取消</el-button>
        <el-button type="primary" @click="handleSubmit(ruleFormRef)">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
  import { reactive, ref, toRefs, PropType } from 'vue';
  import { ItemMap } from './items';
  import { BaseFormItem, FormConfigType, SaverConfigType } from './common-form-type';
  // import { excempleInput } from './dataExcemple';

  interface FD {
    fd: any;
    rules: any;
  }
  type FormInstance = /*unresolved*/ any;
  // 预处理方法 - 初始化 formData 和 rules
  const getFormData = (arr: Array<BaseFormItem>): FD => {
    let fd: any = {};
    let rules: any = {};

    arr.forEach((item) => {
      fd[item.prop] = item.defaultValue;
      rules[item.prop] = item.rules;
    });

    return { fd, rules };
  };

  // 获取 props
  const props = defineProps({
    saverConfig: {
      type: Object as PropType<SaverConfigType>,
      default: (): SaverConfigType => ({
        title: '弹框',
        width: '40%',
        appendToBody: false,
        submitMethod: async (formData) => {
          console.log(formData);
          return true;
        },
      }),
    },
    formItems: {
      type: Array as PropType<Array<BaseFormItem>>,
      default: () => [{ name: 'input', prop: 'username', label: '用户名', placeholder: '请输入用户名' }],
    },
    formConfig: { type: Object as PropType<FormConfigType>, default: () => ({}) },
  });

  // 初始化 数据
  const dialogVisible = ref(false); // 开关
  const ruleFormRef = ref<FormInstance>(); // 表单 Ref
  const saverRef = ref();
  const { formItems, saverConfig, formConfig } = toRefs(props); // 将 props 转换成双向绑定
  const formData = reactive(getFormData(formItems.value).fd); // 绑定 formData
  const rules = reactive(getFormData(formItems.value).rules); // 绑定 rules
  const dialogType = ref<'新建' | '编辑' | '查看'>('编辑');
  // 测试 watch 方法 deep
  // watch(formData, (v, o) => {
  //   console.log('v=', v, ',o=', o);
  // });

  // 接收子组件回调 - 更新数据
  const handleUpdate = (c: any): void => {
    formData[c.prop] = c.val;
  };

  // 声明 emits ，放在下面因为准备把方法放在最下面
  // const emits = defineEmits({
  //   handleSearch: null,
  // });

  // 操作 - 提交
  const handleSubmit = (formRef: FormInstance | undefined) => {
    formRef &&
      formRef.validate((v: boolean) => {
        if (v) {
          console.warn('submit!');
          saverConfig.value.submitMethod && saverConfig.value.submitMethod(formData, saverRef.value);
        } else {
          console.error('submit fiald!', formData);
          return false;
        }
      });
  };

  // 操作 - 取消
  const resetForm = (formRef: FormInstance | undefined) => {
    formRef && formRef.resetFields();
    dialogVisible.value = false;
  };

  const handleOpen = (type: '新建' | '编辑' | '查看') => {
    dialogType.value = type;
    dialogVisible.value = true;
  };
  const handleClose = (): void => resetForm(ruleFormRef.value);

  // 对外暴露属性和方法
  defineExpose({ formData, handleOpen, handleClose });
</script>
